package com.higgins.server.agentapp.service;

import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.logging.Logger;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.higgins.client.agentapp.datamodel.AdvertisedJobDTO;
import com.higgins.client.agentapp.datamodel.AgencyDTO;
import com.higgins.client.agentapp.datamodel.AgentDTO;
import com.higgins.client.agentapp.datamodel.CorrespondenceDTO;
import com.higgins.client.agentapp.datamodel.JobSiteDTO;
import com.higgins.client.agentapp.service.AgentAppService;
import com.higgins.client.dataModel.CoveringLetterDTO;
import com.higgins.client.dataModel.StrategyDTO;
import com.higgins.server.Strategy;
import com.higgins.server.agentapp.datamodel.AdvertisedJob;
import com.higgins.server.agentapp.datamodel.Agency;
import com.higgins.server.agentapp.datamodel.Agent;
import com.higgins.server.agentapp.datamodel.Correspondence;
import com.higgins.server.agentapp.datamodel.JobSite;
import com.higgins.server.knowledge.KnowledgeServiceImpl;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;

/**
 * The server side implementation of the RPC service.
 */
@SuppressWarnings("serial")
public class AgentAppServiceImpl extends com.seguedevelopment.gwtrpccommlayer.server.GwtRpcCommLayerServlet implements
		AgentAppService {
	private static final Logger log = Logger.getLogger(AgentAppServiceImpl.class.getName());
	private EntityManagerFactory emfInstance = Persistence
			.createEntityManagerFactory("com.higgins.server.jpa");

	public AgentAppServiceImpl()	{		 
	}
	public void doGet(HttpServletRequest req, HttpServletResponse resp)	throws IOException	{
		log.info("Ping Received!");
	}
	@Override
	public List<JobSiteDTO> retrieveJobSites() throws IllegalArgumentException {
		EntityManager entityManager = emfInstance.createEntityManager();
		Query query = entityManager.createQuery( "from JobSite s");
		List<JobSite> list = query.getResultList();
		System.out.println("Size of list = " + list.size());
		List<JobSiteDTO> dtoList = new ArrayList<JobSiteDTO>();
		for (JobSite jobSite:list)	{
			JobSiteDTO dto = jobSite.toDTO();
			dtoList.add(dto);
		}
		entityManager.close();	
		return dtoList;
	}

	public JobSite retrieveJobSite(EntityManager entityManager, Long id) throws IllegalArgumentException {
		Query query = entityManager.createQuery( "from JobSite s where s.id = :arg1");
		query.setParameter("arg1", id);
		List<JobSite> list = query.getResultList();
		System.out.println("Size of list = " + list.size());
		if (list.size() > 0)
			return list.get(0);
		else 
			return null;
	}
			
	@Override
	public String updateJobSite(JobSiteDTO dto) throws IllegalArgumentException {
		EntityManager entityManager = emfInstance.createEntityManager();
		entityManager.getTransaction().begin();
		
		JobSite jobsite = dto.getId()!=null?retrieveJobSite(entityManager, dto.getId()):new JobSite();
		jobsite.update(dto);	
		
		entityManager.persist(jobsite);
		entityManager.getTransaction().commit();
		entityManager.close();		
		return jobsite.getId().toString();	
	}
	
	
	
	
	
	
	@Override
	public List<AgencyDTO> retrieveAgencys() throws IllegalArgumentException {
		EntityManager entityManager = emfInstance.createEntityManager();
		Query query = entityManager.createQuery( "from Agency s");
		List<Agency> list = query.getResultList();
		System.out.println("Size of list = " + list.size());
		List<AgencyDTO> dtoList = new ArrayList<AgencyDTO>();
		for (Agency agency:list)	{
			AgencyDTO dto = agency.toDTO();
			dtoList.add(dto);
		}
		entityManager.close();	
		return dtoList;
	}

	public Agency retrieveAgency(EntityManager entityManager, Long id) throws IllegalArgumentException {
		Query query = entityManager.createQuery( "from Agency s where s.id = :arg1");
		query.setParameter("arg1", id);
		List<Agency> list = query.getResultList();
		System.out.println("Size of list = " + list.size());
		if (list.size() > 0)
			return list.get(0);
		else 
			return null;
	}
			
	@Override
	public String updateAgency(AgencyDTO dto) throws IllegalArgumentException {
		EntityManager entityManager = emfInstance.createEntityManager();
		entityManager.getTransaction().begin();
		
		Agency agency = dto.getId()!=null?retrieveAgency(entityManager, dto.getId()):new Agency();
		agency.update(dto);	
		
		entityManager.persist(agency);
		entityManager.getTransaction().commit();
		entityManager.close();		
		return agency.getId().toString();	
	}	
	
	
	@Override
	public List<AgentDTO> retrieveAgents(Long agencyId) throws IllegalArgumentException {
		EntityManager entityManager = emfInstance.createEntityManager();
		Query query;
		if (agencyId!=null)	{
			query= entityManager.createQuery( "from Agent s where s.agency = :arg1");
			query.setParameter("arg1", retrieveAgency(entityManager, agencyId));
		} else {
			query= entityManager.createQuery( "from Agent s ");
		}
		List<Agent> list = query.getResultList();
		System.out.println("Size of list = " + list.size());
		List<AgentDTO> dtoList = new ArrayList<AgentDTO>();
		for (Agent agent:list)	{
			AgentDTO dto = agent.toDTO();
			dtoList.add(dto);
		}
		entityManager.close();	
		return dtoList;
	}

	public Agent retrieveAgent(EntityManager entityManager, Long id) throws IllegalArgumentException {
		Query query = entityManager.createQuery( "from Agent s where s.id = :arg1");
		query.setParameter("arg1", id);
		List<Agent> list = query.getResultList();
		System.out.println("Size of list = " + list.size());
		if (list.size() > 0)
			return list.get(0);
		else 
			return null;
	}
			
	@Override
	public String updateAgent(AgentDTO dto) throws IllegalArgumentException {
		EntityManager entityManager = emfInstance.createEntityManager();
		entityManager.getTransaction().begin();
		
		Agent agent = dto.getId()!=null?retrieveAgent(entityManager, dto.getId()):new Agent();
		agent.update(dto);	
		
		if (dto.getAgencyDTO()!=null)	{
			Agency agency = retrieveAgency(entityManager, dto.getAgencyDTO().getId());
			agent.setAgency(agency);
		}
		
		entityManager.persist(agent);
		entityManager.getTransaction().commit();
		entityManager.close();		
		return agent.getId().toString();	
	}

	@Override
	public List<AdvertisedJobDTO> retrieveAdvertisedJobs()
			throws IllegalArgumentException {
		EntityManager entityManager = emfInstance.createEntityManager();
		Query query = entityManager.createQuery( "from AdvertisedJob s ");
		List<AdvertisedJob> list = query.getResultList();
		System.out.println("Size of list = " + list.size());
		List<AdvertisedJobDTO> dtoList = new ArrayList<AdvertisedJobDTO>();
		for (AdvertisedJob advertisedJob:list)	{
			AdvertisedJobDTO dto = advertisedJob.toDTO();
			dtoList.add(dto);
		}
		entityManager.close();	
		Collections.sort(dtoList, new Comparator<AdvertisedJobDTO>() {
            @Override
            public int compare(AdvertisedJobDTO arg0, AdvertisedJobDTO arg1) {
                Date d1 = arg0.getTimestamp();
                Date d2 = arg1.getTimestamp();
                return (d1.getTime() > d2.getTime() ? -1 : 1);     //descending
            }
		});
		return dtoList;
	}
	
	@Override
	public List<AdvertisedJobDTO> retrieveAdvertisedJobsByAgencyId(Long agencyId)
			throws IllegalArgumentException {
		EntityManager entityManager = emfInstance.createEntityManager();
		Query query = entityManager.createQuery( "from AdvertisedJob s where s.agency = :arg1");
		query.setParameter("arg1", retrieveAgency(entityManager, agencyId));
		List<AdvertisedJob> list = query.getResultList();
		System.out.println("Size of list = " + list.size());
		List<AdvertisedJobDTO> dtoList = new ArrayList<AdvertisedJobDTO>();
		for (AdvertisedJob advertisedJob:list)	{
			AdvertisedJobDTO dto = advertisedJob.toDTO();
			dtoList.add(dto);
		}
		entityManager.close();	
		return dtoList;
	}

	@Override
	public List<AdvertisedJobDTO> retrieveAdvertisedJobsByAgentId(Long agentId)
			throws IllegalArgumentException {
		EntityManager entityManager = emfInstance.createEntityManager();
		Query query = entityManager.createQuery( "from AdvertisedJob s where s.agent = :arg1");
		query.setParameter("arg1", retrieveAgent(entityManager, agentId));
		List<AdvertisedJob> list = query.getResultList();
		System.out.println("Size of list = " + list.size());
		List<AdvertisedJobDTO> dtoList = new ArrayList<AdvertisedJobDTO>();
		for (AdvertisedJob advertisedJob:list)	{
			AdvertisedJobDTO dto = advertisedJob.toDTO();
			dtoList.add(dto);
		}
		entityManager.close();	
		return dtoList;
	}		
	public AdvertisedJob retrieveAdvertisedJob(EntityManager entityManager, Long id) throws IllegalArgumentException {
		Query query = entityManager.createQuery( "from AdvertisedJob s where s.id = :arg1");
		query.setParameter("arg1", id);
		List<AdvertisedJob> list = query.getResultList();
		System.out.println("Size of list = " + list.size());
		if (list.size() > 0)
			return list.get(0);
		else 
			return null;
	}
	@Override
	public String updateAdvertisedJob(AdvertisedJobDTO dto)
			throws IllegalArgumentException {
		EntityManager entityManager = emfInstance.createEntityManager();
		entityManager.getTransaction().begin();
		
		AdvertisedJob advertisedJob = dto.getId()!=null?retrieveAdvertisedJob(entityManager, dto.getId()):new AdvertisedJob();
		advertisedJob.update(dto);	
		
		if (dto.getJobSiteDTO()!=null)	{
			JobSite jobSite = retrieveJobSite(entityManager, dto.getJobSiteDTO().getId());
			advertisedJob.setJobSite(jobSite);
		}
		if (dto.getAgencyDTO()!=null)	{
			Agency agency = retrieveAgency(entityManager, dto.getAgencyDTO().getId());
			advertisedJob.setAgency(agency);
		}
		if (dto.getAgentDTO()!=null)	{
			Agent agent = retrieveAgent(entityManager, dto.getAgentDTO().getId());
			advertisedJob.setAgent(agent);
		}
		
		entityManager.persist(advertisedJob);
		entityManager.getTransaction().commit();
		entityManager.close();		
		return advertisedJob.getId().toString();	
	}
    @Override
    public Boolean deleteAdvertisedJob(Long advertisedJobId)
            throws IllegalArgumentException {
        EntityManager entityManager = emfInstance.createEntityManager();
        entityManager.getTransaction().begin();
        
        AdvertisedJob advertisedJob = retrieveAdvertisedJob(entityManager, advertisedJobId);
        entityManager.remove(advertisedJob);
        entityManager.getTransaction().commit();
        entityManager.close();
        return true;
    }

	@Override
	public List<CorrespondenceDTO> retrieveCorrespondences(Long advertisedJobId)
			throws IllegalArgumentException {
		EntityManager entityManager = emfInstance.createEntityManager();
		Query query = entityManager.createQuery( "from Correspondence s where s.advertisedJob = :arg1");
		query.setParameter("arg1", retrieveAdvertisedJob(entityManager, advertisedJobId));
		List<Correspondence> list = query.getResultList();
		System.out.println("Size of list = " + list.size());
		List<CorrespondenceDTO> dtoList = new ArrayList<CorrespondenceDTO>();
		for (Correspondence correspondence:list)	{
			CorrespondenceDTO dto = correspondence.toDTO();
			dtoList.add(dto);
		}
		entityManager.close();	
        Collections.sort(dtoList, new Comparator<CorrespondenceDTO>() {
            @Override
            public int compare(CorrespondenceDTO arg0, CorrespondenceDTO arg1) {
                Date d1 = arg0.getTimestamp();
                Date d2 = arg1.getTimestamp();
                return (d1.getTime() > d2.getTime() ? -1 : 1);     //descending
            }
        });
		
		return dtoList;
	}
	public Correspondence retrieveCorrespondence(EntityManager entityManager, Long id) throws IllegalArgumentException {
		Query query = entityManager.createQuery( "from Correspondence s where s.id = :arg1");
		query.setParameter("arg1", id);
		List<Correspondence> list = query.getResultList();
		System.out.println("Size of list = " + list.size());
		if (list.size() > 0)
			return list.get(0);
		else 
			return null;
	}
	@Override
	public String updateCorrespondence(CorrespondenceDTO dto)
			throws IllegalArgumentException {
		EntityManager entityManager = emfInstance.createEntityManager();
		entityManager.getTransaction().begin();
		
		Correspondence correspondence = dto.getId()!=null?retrieveCorrespondence(entityManager, dto.getId()):new Correspondence();
		correspondence.update(dto);	
		
		if (dto.getAdvertisedJobDTO()!=null)	{
			AdvertisedJob advertisedJob = retrieveAdvertisedJob(entityManager, dto.getAdvertisedJobDTO().getId());
			correspondence.setAdvertisedJob(advertisedJob);
		}
		if (dto.getAgentDTO()!=null)	{
			Agent agent = retrieveAgent(entityManager, dto.getAgentDTO().getId());
			correspondence.setAgent(agent);
		}
		entityManager.persist(correspondence);
		entityManager.getTransaction().commit();
		entityManager.close();		
		return correspondence.getId().toString();	
	}
    @Override
    public Boolean deleteCorrespondence(Long correspondenceId)
            throws IllegalArgumentException {
        EntityManager entityManager = emfInstance.createEntityManager();
        entityManager.getTransaction().begin();
        
        Correspondence correspondence = retrieveCorrespondence(entityManager, correspondenceId);
        entityManager.remove(correspondence);
        entityManager.getTransaction().commit();
        entityManager.close();
        return true;
    }
}
